import { _decorator, Component, Node, Prefab, Vec3 } from 'cc';
import { DataManager, WeaponConfig } from '../Core/DataManager';
import { ObjectPool } from '../Core/ObjectPool';

const { ccclass, property } = _decorator;

/**
 * Base class for all weapons
 */
@ccclass('WeaponBase')
export abstract class WeaponBase extends Component {
    @property
    protected weaponId: string = "";

    @property
    protected level: number = 1;

    @property
    protected attackRange: number = 5;

    @property
    protected fireRate: number = 1;

    @property
    protected damage: number = 10;

    @property(Prefab)
    protected bulletPrefab: Prefab = null;

    // Timer for tracking fire rate
    protected _fireTimer: number = 0;
    
    // Reference to weapon configuration
    protected _config: WeaponConfig = null;
    
    // Reference to the player
    protected _player: Node = null;
    
    // Reference to the target enemy
    protected _target: Node = null;

    start() {
        // Get weapon configuration from DataManager
        this._config = DataManager.instance.getWeaponConfig(this.weaponId);
        
        // Apply configuration values if available
        if (this._config) {
            this.attackRange = this._config.attackRange;
            this.fireRate = this._config.fireRate;
            this.damage = this._config.damage;
        }
        
        // Find the player node (assuming the weapon is a child of the player)
        this._player = this.node.parent;
        
        // Initialize weapon
        this.initialize();
    }

    /**
     * Initialize the weapon
     * Override this method in derived classes to add specific initialization logic
     */
    protected initialize(): void {
        // Register bullet prefab with object pool if applicable
        if (this.bulletPrefab) {
            ObjectPool.instance.registerPrefab(this.weaponId + "_bullet", this.bulletPrefab, 10);
        }
    }

    update(deltaTime: number) {
        // Update the fire timer
        this._fireTimer += deltaTime;
        
        // Find target
        this.findTarget();
        
        // Try to attack
        if (this._fireTimer >= 1 / this.fireRate) {
            this.attack();
            this._fireTimer = 0;
        }
    }

    /**
     * Find the nearest target within attack range
     * Override this method in derived classes if necessary
     */
    protected findTarget(): void {
        // Get all enemies in the scene
        const enemies = this.node.scene.getComponentsInChildren('EnemyController');
        
        // Find the nearest enemy within attack range
        let nearestEnemy: Node = null;
        let minDistance = this.attackRange;
        
        for (const enemy of enemies) {
            const distance = Vec3.distance(this.node.worldPosition, enemy.node.worldPosition);
            if (distance < minDistance) {
                minDistance = distance;
                nearestEnemy = enemy.node;
            }
        }
        
        this._target = nearestEnemy;
    }

    /**
     * Attack the target
     * This method must be implemented by derived classes
     */
    protected abstract attack(): void;

    /**
     * Upgrade the weapon to the next level
     */
    public upgrade(): void {
        this.level++;
        
        // Apply upgrades from configuration
        if (this._config && this._config.upgradeOptions) {
            const upgradeInfo = this._config.upgradeOptions.find(u => u.level === this.level);
            
            if (upgradeInfo) {
                this.damage = upgradeInfo.damage;
                this.fireRate = upgradeInfo.fireRate;
                this.attackRange = upgradeInfo.attackRange;
                
                // Apply additional effects if any
                this.applyUpgradeEffects(upgradeInfo.extraEffects);
            }
        }
    }

    /**
     * Apply additional upgrade effects
     * Override this method in derived classes to handle specific upgrade effects
     */
    protected applyUpgradeEffects(effects: string[]): void {
        // Base implementation does nothing
    }

    /**
     * Get the current level of the weapon
     */
    public getLevel(): number {
        return this.level;
    }

    /**
     * Get the weapon's ID
     */
    public getWeaponId(): string {
        return this.weaponId;
    }

    /**
     * Get the weapon's damage
     */
    public getDamage(): number {
        return this.damage;
    }

    /**
     * Get the weapon's attack range
     */
    public getAttackRange(): number {
        return this.attackRange;
    }

    /**
     * Get the weapon's fire rate
     */
    public getFireRate(): number {
        return this.fireRate;
    }
} 